package com.shadow.demo.dictionary.common;


import info.monitorenter.cpdetector.io.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件工具类
 *
 * @author penggch
 */
@Slf4j
public class FileUtil {

    private static Map<String, Long> fileModifyMap = new HashMap<String, Long>();
    private static Map<String, Long> fileLengthMap = new HashMap<String, Long>();
    private static Object lock = new Object();
    /**
     * Windows路径分隔符
     */
    public static final char WINDOWS_SEPARATOR = '\\';

    /**
     * 判断文件是否发生修改
     *
     * @param file 文件
     * @return 文件不存在，返回false；第一次加载，返回true；发生了修改返回true；未发生修改，返回false
     */
    public static boolean isModified(File file) {
        boolean result = false;
        if (file != null && file.exists()) {
            if (fileModifyMap.containsKey(file.getAbsolutePath())) {
                if (!fileModifyMap.get(file.getAbsolutePath()).equals(file.lastModified())
                        || !fileLengthMap.get(file.getAbsolutePath()).equals(file.length())) {
                    result = true;
                }
            } else {
                result = true;
                synchronized (lock) {
                    fileModifyMap.put(file.getAbsolutePath(), file.lastModified());
                    fileLengthMap.put(file.getAbsolutePath(), file.length());
                }
            }
        }

        return result;
    }

    /**
     * 获取修改后的文件
     *
     * @param file 文件
     * @return 若文件发生了修改，返回文件；否则，返回null
     */
    public static File getModifiedFile(File file) {
        if (isModified(file)) {
            return file;
        } else {
            return null;
        }
    }

    /**
     * 获取修改后的文件
     *
     * @param file 文件
     * @return 若文件发生了修改，返回文件；否则，返回null
     */
    public static File getModifiedFile(String file) {
        File f = new File(file);
        if (isModified(f)) {
            return f;
        } else {
            return null;
        }
    }

    //删除文件夹
    public static void delFolder(String folderPath) {
        try {
            //删除完里面所有内容
            delAllFile(folderPath);
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            //删除空文件夹
            if (!myFilePath.delete()) {
                log.warn("删除文件失败");
            }
        } catch (Exception e) {
            log.error("", e);
        }
    }

    //删除指定文件夹下所有文件
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        if (tempList == null) {
            return flag;
        }
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp == null) {
                continue;
            }
            if (temp.isFile()) {
                if (!temp.delete()) {
                    log.warn("删除文件失败：{}", temp.getPath());
                }
            }
            if (temp.isDirectory()) {
                //先删除文件夹里面的文件
                if (!delAllFile(path + "/" + tempList[i])) {
                    log.warn("删除文件夹内文件失败：" + path + "/" + tempList[i]);
                }
                //再删除空文件夹
                delFolder(path + "/" + tempList[i]);
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 创建目录
     *
     * @param path 目录
     */
    public static void mkDir(String path) {
        File file = new File(path);
        mkDir(file);
    }

    /**
     * 创建目录
     *
     * @param file
     */
    public static void mkDir(File file) {
        if (file.getParentFile().exists()) {
            if(!file.mkdir()) {
                log.warn("创建文件夹失败：{}", file.getPath());
            }
        } else {
            mkDir(file.getParentFile());
            if(!file.mkdir()) {
                log.warn("创建文件夹失败：{}", file.getPath());
            }
        }
    }

    /**
     * 文件大小处理
     *
     * @param fileS
     */
    public static String formatFileSize(long fileS) {
        //转换文件大小
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "K";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "M";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "G";
        }
        return fileSizeString;
    }

    public static String getCharset(File file) {
        CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
        detector.add(new ParsingDetector(false));
        detector.add(JChardetFacade.getInstance());
        detector.add(ASCIIDetector.getInstance());
        detector.add(UnicodeDetector.getInstance());
        Charset charset = null;
        try {
            charset = detector.detectCodepage(file.toURL());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        if (charset != null) {
            return charset.name();
        } else {
            return "";
        }
    }

    /**
     * 将JavaFile对象转化为 MultipartFile
     *
     * @param fieldName MultipartFile 变量名
     * @param file      File
     * @return MultipartFile
     */
    public static MultipartFile fileToMultipart(String fieldName, File file) {
        FileItem fileItem = new DiskFileItemFactory()
                .createItem("file", MediaType.MULTIPART_FORM_DATA_VALUE, true, file.getName());
        InputStream is = null;
        OutputStream os = null;
        try {
            os = fileItem.getOutputStream();
            is = new BufferedInputStream(new FileInputStream(file));
            IoUtil.write(is, os);
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            IoUtil.closeQuietly(is);
            IoUtil.closeQuietly(os);
        }
        return new CommonsMultipartFile(fileItem);
    }
}
